home *** CD-ROM | disk | FTP | other *** search
- /* XView panel stuff.
- Copyright (C) 1995 Jakub Jelinek.
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
-
- #include <config.h>
- #include <X11/Xatom.h>
- #include <xview/xview.h>
- #include <xview/frame.h>
- #include <xview/panel.h>
- #include <xview/canvas.h>
- #include <xview/scrollbar.h>
- #include <xview/svrimage.h>
- #include <xview/win_event.h>
- #include <xview/cms.h>
- #include <xview/dragdrop.h>
- #include <xview/cursor.h>
- #include <xview/rect.h>
- #include <string.h>
-
- #include "mad.h"
- #include "mem.h"
- #include "fs.h"
- #include "dir.h"
- #include "panel.h"
- #include "dlg.h"
- #include "widget.h"
- #include "command.h"
- #include "cmd.h"
- #include "main.h"
- #include "xvmain.h"
- #include "xvscreen.h"
- #include "util.h"
-
- void do_enter (WPanel *panel);
-
- extern Server_image iconRegular [2];
- extern Server_image iconDirectory [2];
-
- extern WPanel *current_panel;
- extern WCommand *cmdline;
- extern Cursor dropcursor;
- extern Dlg_head *midnight_dlg;
- extern Cms mccms;
- extern Display *dpy;
-
- extern int is_right;
-
- #define PANELITEMBORDER 2
- #define PANELBORDER 4
-
- static void xv_panel_repaint_proc (Canvas canvas, Xv_Window paint_window,
- Rectlist *repaint);
-
- void show_dir (WPanel *panel)
- {
- /* This routine should update the current directory label */
- xv_set ((Frame) xv_get ((Canvas) panel->widget.wdata, XV_OWNER),
- FRAME_LABEL, panel->cwd,
- NULL);
- }
-
- void xv_set_current_panel (WPanel *panel)
- {
- if (panel != current_panel)
- change_panel ();
- }
-
- int x_panel_load_index (WPanel *panel, int idx)
- {
- return 0;
- }
-
- void xv_clear_area (Xv_window xv_win, Rect *rect)
- {
- XClearArea (dpy, xv_get (xv_win, XV_XID),
- rect->r_left, rect->r_top,
- rect->r_width, rect->r_height,
- FALSE);
- }
-
- void xv_invalidate_rect (Canvas canvas, Rect *rect)
- {
- Xv_window xv_win, xv_view;
- Scrollbar scrollbar;
- Rect rec;
- int i, j;
- Rectlist rl;
- Rectnode rn;
-
- CANVAS_EACH_PAINT_WINDOW (canvas, xv_win)
- if (rect == NULL) {
- rec.r_left = 0;
- rec.r_top = 0;
- rec.r_width = xv_get (xv_win, XV_WIDTH);
- rec.r_height = xv_get (xv_win, XV_HEIGHT);
- xv_clear_area (xv_win, &rec);
- } else
- rec = *rect;
- xv_view = xv_get (xv_win, CANVAS_PAINT_VIEW_WINDOW);
- scrollbar = (Scrollbar) xv_get (canvas, OPENWIN_HORIZONTAL_SCROLLBAR, xv_win);
- if (scrollbar != XV_NULL) {
- i = xv_get (scrollbar, SCROLLBAR_VIEW_START);
- j = xv_get (xv_view, XV_WIDTH);
- if (rec.r_left < i)
- rec.r_left = i;
- if (rec.r_left + rec.r_width > i + j)
- rec.r_width = i + j - rec.r_left;
- }
- scrollbar = (Scrollbar) xv_get (canvas, OPENWIN_VERTICAL_SCROLLBAR, xv_win);
- if (scrollbar != XV_NULL) {
- i = xv_get (scrollbar, SCROLLBAR_VIEW_START) *
- xv_get (scrollbar, SCROLLBAR_PIXELS_PER_UNIT);
- j = xv_get (xv_view, XV_HEIGHT);
- if (rec.r_top < i)
- rec.r_top = i;
- if (rec.r_top + rec.r_height > i + j)
- rec.r_height = i + j - rec.r_top;
- }
- rn.rn_next = NULL;
- rn.rn_rect = rec;
- rl.rl_x = 0;
- rl.rl_y = 0;
- rl.rl_head = rl.rl_tail = &rn;
- rl.rl_bound = rec;
- xv_panel_repaint_proc (canvas, xv_win, &rl);
- CANVAS_END_EACH
- }
-
- void xv_invalidate_item (Canvas canvas, int idx)
- {
- Rect rect;
- WPanel *panel = (WPanel *) xv_get (canvas, XV_KEY_DATA, KEY_DATA_PANEL);
-
- rect_construct (&rect, PANELBORDER, PANELBORDER + panel->item_height * idx,
- panel->total_width, panel->item_height);
- xv_invalidate_rect (canvas, &rect);
- }
-
- /* This procedure should be called whenever we change a f.marked file attribute
- as a result of the program action, not by user clicking */
- void x_panel_select_item (WPanel *panel, int idx, int value)
- {
- Canvas canvas = (Canvas) (panel->widget.wdata);
-
- xv_invalidate_item (canvas, idx);
- }
-
- typedef enum {
- MIP_UP, MIP_DOWN, MIP_PAGEUP, MIP_PAGEDOWN, MIP_HOME, MIP_END,
- } mipaction;
-
- static void moveinpanel (Canvas canvas, Xv_window paint, mipaction action)
- {
- WPanel *panel = (WPanel *) xv_get (canvas, XV_KEY_DATA, KEY_DATA_PANEL);
- Scrollbar scroll = (Scrollbar) xv_get (canvas, OPENWIN_VERTICAL_SCROLLBAR,
- xv_get (paint, CANVAS_PAINT_VIEW_WINDOW));
- int newsel, newstart;
- int start = xv_get (scroll, SCROLLBAR_VIEW_START);
- int length = xv_get (scroll, SCROLLBAR_VIEW_LENGTH);
- int lasttop = panel->count - length;
-
- newstart = start;
- newsel = panel->selected;
- switch (action) {
- case MIP_PAGEUP:
- if (newsel > start)
- newsel = start;
- else {
- newstart -= length - 1;
- newsel -= length - 1;
- }
- break;
- case MIP_PAGEDOWN:
- if (newsel < start + length - 1)
- newsel = start + length - 1;
- else {
- newstart += length - 1;
- newsel += length - 1;
- }
- break;
- case MIP_HOME:
- newsel = 0;
- newstart = 0;
- break;
- case MIP_END:
- newsel = panel->count - 1;
- newstart = lasttop;
- break;
- case MIP_UP:
- if (newsel <= start)
- newstart -= length / 2 - 1;
- newsel--;
- break;
- case MIP_DOWN:
- if (newsel >= start + length - 1) {
- newstart += length / 2 - 1;
- }
- newsel++;
- break;
- }
- if (newsel > panel->count - 1)
- newsel = panel->count - 1;
- if (newsel < 0)
- newsel = 0;
- if (newstart > lasttop)
- newstart = lasttop;
- if (newstart < 0)
- newstart = 0;
-
- if (newstart != start || newsel != panel->selected) {
- if (newstart != start)
- xv_set (scroll,
- SCROLLBAR_VIEW_START, newstart,
- NULL);
-
- if (newsel != panel->selected) {
- unselect_item (panel);
- panel->selected = newsel;
- select_item (panel);
- }
-
- }
- }
-
- static WPanel *drag_panel;
- struct copy_move_in_panel {
- int copy;
- char *to;
- WPanel *from;
- };
-
- static copymove_in_panel (struct copy_move_in_panel *cmip)
- {
- WPanel *panel = current_panel;
-
- xv_set_current_panel (cmip->from);
- copymove_cmd_with_default (cmip->copy, cmip->to);
- free (cmip->to);
- free (cmip);
- xv_set_current_panel (panel);
- }
-
- static void delete_cmd_in_panel (WPanel *panel)
- {
- xv_set_current_panel (panel);
- delete_cmd ();
- }
-
- struct user_drop {
- WPanel *panel;
- char *filename;
- char *drops;
- };
-
- static user_drop (struct user_drop *usdr)
- {
- WPanel *panel = current_panel;
-
- xv_set_current_panel (usdr->panel);
- regex_command (usdr->filename, "Drop", usdr->drops);
- free (usdr->drops);
- free (usdr);
- xv_set_current_panel (panel);
- }
-
- static int selection_convert (Selection_owner seln, Atom *type, Xv_opaque *data,
- unsigned long *length, int *format)
- {
- Xv_Server server = XV_SERVER_FROM_WINDOW (xv_get (seln, XV_OWNER));
-
- if (*type == (Atom) xv_get (server, SERVER_ATOM, "_SUN_SELECTION_END") ||
- *type == (Atom) xv_get (server, SERVER_ATOM, "_SUN_DRAGDROP_DONE")) {
- *format = 32;
- *length = 0;
- *data = XV_NULL;
- *type = (Atom) xv_get (server, SERVER_ATOM, "NULL");
- return TRUE;
- } else if (*type == (Atom) xv_get (server, SERVER_ATOM, "DELETE")) {
- xv_post_proc (midnight_dlg, (void (*)(void *))delete_cmd_in_panel,
- (void *) drag_panel);
- *format = 32;
- *length = 0;
- *data = XV_NULL;
- *type = (Atom) xv_get (server, SERVER_ATOM, "NULL");
- return TRUE;
- } else
- return sel_convert_proc (seln, type, data, length, format);
- }
-
- static void start_drag (Xv_window paint, Event *event, Canvas canvas)
- {
- Dnd dnd;
- Selection_item sel_item;
- WPanel *panel;
- char *p, *q;
- int i, copy = (event_shift_is_down (event) || event_ctrl_is_down (event));
- int trailslash;
- Xv_Server server = XV_SERVER_FROM_WINDOW (paint);
-
- drag_panel = panel = (WPanel *) xv_get (canvas, XV_KEY_DATA, KEY_DATA_PANEL);
- dnd = xv_create (paint, DRAGDROP,
- DND_TYPE, i ? DND_COPY : DND_MOVE,
- SEL_CONVERT_PROC, selection_convert,
- DND_ACCEPT_CURSOR, dropcursor,
- NULL);
- if (i) {
- xv_set (dnd,
- DND_CURSOR, xv_create (XV_NULL, CURSOR,
- CURSOR_SRC_CHAR, OLC_COPY_PTR,
- CURSOR_MASK_CHAR, OLC_COPY_MASK_PTR,
- NULL),
- NULL);
- } else
- xv_set (dnd,
- DND_CURSOR, xv_create (XV_NULL, CURSOR,
- CURSOR_SRC_CHAR, OLC_MOVE_PTR,
- CURSOR_MASK_CHAR, OLC_MOVE_MASK_PTR,
- NULL),
- NULL);
- p = "";
- trailslash = (panel->cwd [strlen (panel->cwd) - 1] == '/');
- for (i = 0; i < panel->count; i++)
- if (panel->dir.list [i].f.marked) {
- q = p;
- if (trailslash)
- p = copy_strings (q, panel->cwd, panel->dir.list [i].fname,
- " ", NULL);
- else
- p = copy_strings (q, panel->cwd, "/", panel->dir.list [i].fname,
- " ", NULL);
- if (*q)
- free (q);
- }
- if (!*p) {
- if (trailslash)
- p = copy_strings (panel->cwd,
- panel->dir.list [panel->selected].fname, NULL);
- else
- p = copy_strings (panel->cwd, "/",
- panel->dir.list [panel->selected].fname, " ", NULL);
- }
- sel_item = xv_create (dnd, SELECTION_ITEM,
- SEL_TYPE, (Atom) XA_STRING,
- SEL_DATA, p,
- NULL);
- xv_create (dnd, SELECTION_ITEM,
- SEL_TYPE, (Atom) xv_get (server, SERVER_ATOM, "_MXC_PANELID"),
- SEL_FORMAT, sizeof (WPanel *) * 8,
- SEL_LENGTH, 1,
- SEL_DATA, &drag_panel,
- NULL);
- dnd_send_drop (dnd);
- xv_destroy_safe (dnd);
- }
-
- static void do_drop (Xv_window paint, Event *event, Canvas canvas,
- int in, int idx)
- {
- Selection_requestor sel;
- Xv_server server;
- WPanel **ppanel;
- WPanel *panel;
- char *p;
- int trailslash;
- struct copy_move_in_panel *cmip;
- struct user_drop *usdr;
-
- switch (event_action (event)) {
- case ACTION_DRAG_PREVIEW:
- return;
- case ACTION_DRAG_COPY:
- case ACTION_DRAG_MOVE:
- case ACTION_DRAG_LOAD:
- server = XV_SERVER_FROM_WINDOW (paint);
- sel = (Selection_requestor)
- xv_get (canvas, XV_KEY_DATA, KEY_DATA_SELREQ);
- if (dnd_decode_drop (sel, event) != XV_ERROR) {
- int length, format;
- char *q;
-
- xv_set (sel, SEL_TYPE, XA_STRING, NULL);
- q = (char *) xv_get (sel, SEL_DATA, &length, &format);
- if (length != SEL_ERROR) {
- panel = (WPanel *) xv_get (canvas, XV_KEY_DATA, KEY_DATA_PANEL);
- if (!in || S_ISDIR (panel->dir.list [idx].buf.st_mode)) {
- xv_set (sel,
- SEL_TYPE, (Atom) xv_get (server, SERVER_ATOM, "_MXC_PANELID"),
- NULL);
- ppanel = (WPanel **) xv_get (sel, SEL_DATA, &length, &format);
- trailslash = (panel->cwd [strlen (panel->cwd) - 1] == '/');
- if (length != SEL_ERROR) {
- if (!in) {
- p = strdup (panel->cwd);
- } else {
- if (trailslash)
- p = copy_strings (panel->cwd,
- panel->dir.list [idx].fname, NULL);
- else
- p = copy_strings (panel->cwd, "/",
- panel->dir.list [idx].fname, NULL);
- }
- cmip = (struct copy_move_in_panel *)
- xmalloc (sizeof (struct copy_move_in_panel),
- "Copy/Move in Panel");
- cmip->copy = (event_action (event) == ACTION_COPY);
- cmip->from = *ppanel;
- cmip->to = p;
- xv_post_proc(midnight_dlg,
- (void (*) (void *))copymove_in_panel,
- (void *) cmip);
- free ((char *) ppanel);
- }
- free (q);
- } else {
- usdr = (struct user_drop *)
- xmalloc (sizeof (struct user_drop),
- "User drop");
- usdr->panel = panel;
- usdr->filename = panel->dir.list [idx].fname;
- usdr->drops = q;
- xv_post_proc(midnight_dlg,
- (void (*) (void *))user_drop,
- (void *) usdr);
- }
- }
- xv_set (sel, SEL_TYPE_NAME, "_SUN_SELECTION_END", NULL);
- xv_get (sel, SEL_DATA, &length, &format);
- dnd_done (sel);
- }
- }
- }
-
- static int xv_get_text_len (WPanel *panel, char *text)
- {
- Font_string_dims dims;
-
- xv_get ((Font) (panel->font), FONT_STRING_DIMS, text, &dims);
- return dims.width;
- }
-
- static void xv_insert_panel_item (Canvas canvas, WPanel *panel, int idx)
- {
- int top = panel->fmt_count;
- int just_mode, i, len;
- char *txt;
- file_entry *fe = & panel->dir.list [idx];
- int marked = fe->f.marked;
- int isdir = S_ISDIR (panel->dir.list [idx].buf.st_mode);
- static char buffer [1024];
- char *p = buffer;
-
- for (i = 0; i < top; i++) {
- just_mode = panel->format [i].just_mode;
- if (panel->format [i].string_fn) {
- txt = (*panel->format [i].string_fn) (fe, 0);
- } else
- txt = " ";
- if (panel->format [i].string_fn == string_file_type) {
- panel->format [i].field_len = 18;
- p [0] = 3 + ((*txt == '/') ? 1 : 0);
- p [1] = 0;
- p += 2;
- } else {
- len = xv_get_text_len (panel, txt) + 2;
- if (panel->format [i].field_len < len)
- panel->format [i].field_len = len;
- p [0] = just_mode + 1;
- strcpy (p + 1, txt);
- p = index (p + 1, 0) + 1;
- }
- }
- *(p++) = 0;
- fe->cache = xmalloc (p - buffer, "xview display cache");
- bcopy (buffer, fe->cache, p - buffer);
- }
-
- void x_select_item (WPanel *panel)
- {
- Canvas canvas = (Canvas) panel->widget.wdata;
- int idx = panel->selected;
-
- xv_invalidate_item (canvas, idx);
- }
-
- void x_unselect_item (WPanel *panel)
- {
- Canvas canvas = (Canvas) panel->widget.wdata;
- int idx = panel->selected;
-
- panel->selected = -1;
- xv_invalidate_item (canvas, idx);
- panel->selected = idx;
- }
-
- void x_fill_panel (WPanel *panel)
- {
- int i;
- int w, h;
- Xv_Window win, paint;
- Canvas canvas = (Canvas) panel->widget.wdata;
- Scrollbar scrollbar;
- Rect rect;
-
- for (i = 0; i < panel->fmt_count; i++)
- panel->format [i].field_len = 2;
-
- for (i = 0; i < panel->count; i++)
- xv_insert_panel_item (canvas, panel, i);
-
- for (i = 0, panel->total_width = 2 * PANELITEMBORDER;
- i < panel->fmt_count; i++)
- panel->total_width += panel->format [i].field_len;
-
- w = panel->total_width + 2 * PANELBORDER;
- h = panel->item_height * panel->count + 2 * PANELBORDER;
-
- xv_set (canvas,
- CANVAS_MIN_PAINT_WIDTH, w,
- CANVAS_MIN_PAINT_HEIGHT, h,
- NULL);
-
- i = panel->item_height;
-
- rect.r_left = PANELBORDER;
- rect.r_width = panel->total_width;
- rect.r_top = PANELBORDER;
- rect.r_height = h - 2 * PANELBORDER;
-
- OPENWIN_EACH_VIEW (canvas, win)
- scrollbar = (Scrollbar) xv_get (canvas, OPENWIN_HORIZONTAL_SCROLLBAR, win);
- if (scrollbar != XV_NULL)
- xv_set (scrollbar,
- SCROLLBAR_OBJECT_LENGTH, w,
- NULL);
- scrollbar = (Scrollbar) xv_get (canvas, OPENWIN_VERTICAL_SCROLLBAR, win);
- if (scrollbar != XV_NULL)
- xv_set (scrollbar,
- SCROLLBAR_PIXELS_PER_UNIT, i,
- SCROLLBAR_OBJECT_LENGTH, panel->count + 1,
- NULL);
- paint = (Xv_window) xv_get (win, CANVAS_VIEW_PAINT_WINDOW);
- xv_set (xv_get (paint, XV_KEY_DATA, KEY_DATA_TILE),
- DROP_SITE_DELETE_REGION, NULL,
- DROP_SITE_REGION, &rect,
- NULL);
- OPENWIN_END_EACH
-
- xv_invalidate_rect (canvas, NULL);
-
- }
-
- static void xv_panel_repaint_item (WPanel *panel, int idx, Xv_Window paint_window)
- {
- int selmark = 0;
- file_entry *fe = & panel->dir.list [idx];
- Drawable xid = (Drawable) xv_get (paint_window, XV_XID);
- unsigned long fg, bg, *xc;
- GC gc = (GC) (panel->gc);
- Rect rect;
- char *cache = fe->cache;
- XPoint xp [3];
- char *p;
- int i, w, x, h, y;
- Server_image image, mask;
-
- if (cache == NULL)
- return;
- if (fe->f.marked)
- selmark |= 1;
- if (idx == panel->selected)
- selmark |= 2;
-
- xc = (unsigned long *) xv_get (mccms, CMS_INDEX_TABLE);
-
- fg = xc [selmark * 2 + CMS_CONTROL_COLORS];
- bg = xc [(selmark & 2) ? 1 : 0];
-
- rect_construct (&rect, PANELBORDER, PANELBORDER + idx * panel->item_height,
- panel->total_width, panel->item_height);
-
- XSetForeground (dpy, gc, bg);
- XFillRectangle (dpy, xid, gc,
- rect.r_left,
- rect.r_top,
- rect.r_width,
- rect.r_height);
-
- if (selmark & 2) {
- xp [0].x = rect.r_left;
- xp [0].y = rect.r_top + rect.r_height;
- xp [1].x = rect.r_left;
- xp [1].y = rect.r_top;
- xp [2].x = rect.r_left + rect.r_width - 1;
- xp [2].y = rect.r_top;
- XSetForeground (dpy, gc, xc [2]);
- XDrawLines (dpy, xid, gc, xp, 3, CoordModeOrigin);
- xp [0].x = rect.r_left + 1;
- xp [0].y = rect.r_top + rect.r_height - 1;
- xp [1].x = rect.r_left + rect.r_width - 1;
- xp [1].y = rect.r_top + rect.r_height - 1;
- xp [2].x = rect.r_left + rect.r_width - 1;
- xp [2].y = rect.r_top;
- XSetForeground (dpy, gc, xc [3]);
- XDrawLines (dpy, xid, gc, xp, 3, CoordModeOrigin);
- }
-
- XSetForeground (dpy, gc, fg);
- XSetBackground (dpy, gc, bg);
- rect.r_left += PANELITEMBORDER;
-
- for (i = 0, p = fe->cache; *p; p = strchr (p, 0) + 1, i++) {
- if (*p <= 2) { /* i.e. either left or right justified text */
- w = xv_get_text_len (panel, p + 1);
- h = panel->ascent + panel->descent;
- y = rect.r_top + panel->ascent + (panel->item_height - h) / 2;
- if (*p == J_LEFT + 1)
- x = rect.r_left + 1;
- else
- x = rect.r_left + panel->format [i].field_len - w - 1;
- XDrawString (dpy, xid, gc, x, y, p + 1, strlen (p + 1));
- } else {
- switch (*p) {
- case 3: image = iconRegular [0]; mask = iconRegular [1]; break;
- case 4: image = iconDirectory [0]; mask = iconDirectory [1]; break;
- }
- XSetClipMask (dpy, gc, (Drawable) xv_get (mask, SERVER_IMAGE_PIXMAP));
- x = rect.r_left + 2;
- y = rect.r_top + (panel->item_height - 16) / 2;
- XSetClipOrigin (dpy, gc, x, y);
- XCopyArea (dpy, (Drawable) xv_get (image, SERVER_IMAGE_PIXMAP),
- xid, gc,
- 0, 0,
- 16, 16,
- x, y);
- XSetClipMask (dpy, gc, None);
- }
- rect.r_left += panel->format [i].field_len;
- }
- }
-
- static void xv_panel_repaint_proc (Canvas canvas, Xv_Window paint_window,
- Rectlist *repaint)
- {
- int first, last;
- WPanel *panel;
- int i;
- Rect rect;
-
- panel = (WPanel *) xv_get (canvas, XV_KEY_DATA, KEY_DATA_PANEL);
-
- /* This stuff has to change as soon as we start supporting big icons display */
- first = (repaint->rl_y + repaint->rl_bound.r_top - PANELBORDER) / panel->item_height;
- last = (repaint->rl_y + repaint->rl_bound.r_top + repaint->rl_bound.r_height
- - PANELBORDER - 1) / panel->item_height;
- if (first < 0) {
- first = 0;
- }
- if (last >= panel->count) {
- last = panel->count - 1;
- }
-
- /* First we clear all the areas around... */
-
- if (repaint->rl_x + repaint->rl_bound.r_left < PANELBORDER) {
- rect.r_left = repaint->rl_x + repaint->rl_bound.r_left;
- rect.r_width = PANELBORDER - rect.r_left;
- rect.r_top = repaint->rl_y + repaint->rl_bound.r_top;
- rect.r_height = repaint->rl_bound.r_height;
- xv_clear_area (paint_window, &rect);
- }
-
- if (repaint->rl_x + repaint->rl_bound.r_left + repaint->rl_bound.r_width
- > PANELBORDER + panel->total_width) {
- rect.r_left = PANELBORDER + panel->total_width;
- rect.r_width = repaint->rl_x + repaint->rl_bound.r_left +
- repaint->rl_bound.r_width - rect.r_left;
- rect.r_top = repaint->rl_y + repaint->rl_bound.r_top;
- rect.r_height = repaint->rl_bound.r_height;
- xv_clear_area (paint_window, &rect);
- }
-
- if (repaint->rl_y + repaint->rl_bound.r_top < PANELBORDER) {
- rect.r_left = repaint->rl_x + repaint->rl_bound.r_left;
- rect.r_width = rect.r_left + repaint->rl_bound.r_width;
- if (rect.r_left < PANELBORDER)
- rect.r_left = PANELBORDER;
- if (rect.r_width > panel->total_width + PANELBORDER)
- rect.r_width = panel->total_width + PANELBORDER - rect.r_left;
- else
- rect.r_width -= rect.r_left;
- rect.r_top = repaint->rl_y + repaint->rl_bound.r_top;
- rect.r_height = PANELBORDER - rect.r_top;
- xv_clear_area (paint_window, &rect);
- }
-
- if (repaint->rl_y + repaint->rl_bound.r_top + repaint->rl_bound.r_height
- > PANELBORDER + panel->count * panel->item_height) {
- rect.r_left = repaint->rl_x + repaint->rl_bound.r_left;
- rect.r_width = rect.r_left + repaint->rl_bound.r_width;
- if (rect.r_left < PANELBORDER)
- rect.r_left = PANELBORDER;
- if (rect.r_width > panel->total_width + PANELBORDER)
- rect.r_width = panel->total_width + PANELBORDER - rect.r_left;
- else
- rect.r_width -= rect.r_left;
- rect.r_top = PANELBORDER + panel->count * panel->item_height;
- rect.r_height = repaint->rl_y + repaint->rl_bound.r_top +
- repaint->rl_bound.r_height - rect.r_top;
- xv_clear_area (paint_window, &rect);
- }
-
- for (i = first; i <= last; i++) {
- xv_panel_repaint_item (panel, i, paint_window);
- }
- }
-
- static struct {
- Canvas canvas;
- int idx;
- int btn_down_x, btn_down_y;
- struct timeval prev_time;
- } click_info = { XV_NULL, -1, 0, 0, {0, 0}};
- static int xv_panel_grab = 0;
- static int wait_for_btnup = 0;
- static int rubber_adjust = 0;
- static int lastx, lasty, startx, starty;
- static GC xor_gc;
-
- /* Should select / invert selection of all the idx's inside
- * lastx, startx, lasty, starty
- * As a used side effect, setting lastx = startx = -1 should unmark all files
- */
- static void xv_rubberband_select (WPanel *panel)
- {
- int x1, y1, x2, y2, first, last, i;
-
- x1 = (startx < lastx) ? startx : lastx;
- y1 = (starty < lasty) ? starty : lasty;
- x2 = (startx > lastx) ? startx : lastx;
- y2 = (starty > lasty) ? starty : lasty;
-
- /* This has to change because of big icons */
- if (x2 <= PANELBORDER || x1 >= panel->total_width + PANELBORDER) {
- first = last = -1;
- } else {
- first = (y1 - PANELBORDER) / panel->item_height;
- last = (y2 - PANELBORDER) / panel->item_height;
- }
- for (i = 0; i < panel->count; i++) {
- if (i >= first && i <= last) {
- if (rubber_adjust)
- do_file_mark (panel, i, panel->dir.list [i].f.marked ? 0 : 1);
- else if (!panel->dir.list [i].f.marked)
- do_file_mark (panel, i, 1);
- } else if (!rubber_adjust) {
- if (panel->dir.list [i].f.marked)
- do_file_mark (panel, i, 0);
- }
- }
- }
-
- int is_dbl_click (struct timeval *then, struct timeval *now)
- {
- struct timeval delta;
- static int multiclicktimeout = 0;
-
- delta.tv_sec = now->tv_sec - then->tv_sec;
- if ((delta.tv_usec = now->tv_usec - then->tv_usec) < 0) {
- delta.tv_usec += 1000000;
- delta.tv_sec--;
- }
- if (multiclicktimeout == 0) {
- multiclicktimeout == defaults_get_integer ("mxc.doubleclicktime",
- "Mxc.DoubleClickTime", 5);
- if (multiclicktimeout < 2 || multiclicktimeout > 100)
- multiclicktimeout = 5;
- }
- if ((delta.tv_sec * 10 + delta.tv_usec / 100000) <= multiclicktimeout)
- return 1;
- return 0;
- }
-
- static void draw_rubberband (Canvas canvas)
- {
- Xv_window xv_win;
- int x1, y1, x2, y2, width, height;
-
- x1 = (startx < lastx) ? startx : lastx;
- y1 = (starty < lasty) ? starty : lasty;
- x2 = (startx > lastx) ? startx : lastx;
- y2 = (starty > lasty) ? starty : lasty;
- width = x2 - x1;
- height = y2 - y1;
-
- if (!width || !height)
- return;
-
- CANVAS_EACH_PAINT_WINDOW (canvas, xv_win)
- XDrawRectangle (dpy, xv_get (xv_win, XV_XID), xor_gc, x1, y1,
- width, height);
- CANVAS_END_EACH
- }
-
- static void xv_dblclick_proc (WPanel *panel, int idx)
- {
- xv_set_current_panel (panel);
- if (panel->selected != idx)
- panel->selected = idx; /* Should not happen :) */
- xv_post_proc (midnight_dlg, (void (*)(void *))do_enter, (void *)panel);
- }
-
- static WPanel *xv_filedepmenu_panel = NULL;
- static int xv_filedepmenu_idx;
- static char *xv_filedepmenu_free = NULL;
-
- static void xv_filedepmenu_cmd (char *todo)
- {
- char *p;
-
- p = strchr (todo, ' ');
- *p = 0;
- regex_command (p + 1, todo, NULL);
- free (todo);
- }
-
- static void xv_filedepmenu (Menu menu, Menu_item item)
- {
- char *q;
- char *p = (char *) xv_get (item, MENU_STRING);
-
- if (!strcmp (p, "Copy"))
- xv_post_proc (midnight_dlg, (void (*)(void *))copy_cmd, (void *)NULL);
- else if (!strcmp (p, "Move"))
- xv_post_proc (midnight_dlg, (void (*)(void *))ren_cmd, (void *)NULL);
- else if (!strcmp (p, "Delete"))
- xv_post_proc (midnight_dlg, (void (*)(void *))delete_cmd, (void *)NULL);
- else {
- q = copy_strings (p, " ", xv_filedepmenu_panel->dir.list [xv_filedepmenu_idx].fname, NULL);
- xv_post_proc (midnight_dlg, (void (*)(void *))xv_filedepmenu_cmd, (void *)q);
- }
- if (xv_filedepmenu_free)
- free (xv_filedepmenu_free);
- }
-
- static void xv_mouse_event (Canvas canvas, Xv_window paint, Event *event)
- {
- WPanel *panel = (WPanel *) xv_get (canvas, XV_KEY_DATA, KEY_DATA_PANEL);
- int in, idx;
-
- if (event_x (event) < PANELBORDER ||
- event_x (event) >= PANELBORDER + panel->total_width ||
- event_y (event) < PANELBORDER ||
- event_y (event) >= PANELBORDER + panel->count * panel->item_height) {
- in = 0;
- } else {
- in = 1;
- idx = (event_y (event) - PANELBORDER) / panel->item_height;
- }
- switch (event_action (event)) {
- case ACTION_DRAG_PREVIEW:
- case ACTION_DRAG_COPY:
- case ACTION_DRAG_MOVE:
- case ACTION_DRAG_LOAD:
- do_drop (paint, event, canvas, in, idx);
- return;
- }
- if (xv_panel_grab) {
- if (wait_for_btnup) {
- if (event_action (event) == LOC_DRAG) {
- static int threshold;
- static int dist_x, dist_y;
-
- if (threshold == 0)
- threshold = defaults_get_integer (
- "mxc.clickmovethreshold",
- "Mxc.ClickMoveThreshold", 10);
-
- dist_x = event_x (event) - click_info.btn_down_x;
- if (dist_x < 0)
- dist_x = - dist_x;
- dist_y = event_y (event) - click_info.btn_down_y;
- if (dist_y < 0)
- dist_y = - dist_y;
- if (dist_x > threshold || dist_y > threshold ||
- event_ctrl_is_down (event) || event_shift_is_down (event)) {
- xv_panel_grab = 0;
- wait_for_btnup = 0;
- start_drag (paint, event, canvas);
- }
- return;
- }
- if (event_is_button (event) && event_is_down (event)) {
- return;
- }
- if (event_action (event) == ACTION_SELECT) {
- if (is_dbl_click (&click_info.prev_time, &event_time (event))) {
- /* Should we handle tripple clicks?
- * Maybe for selecting/unselecting all the files :) */
- click_info.prev_time.tv_sec = 0;
- click_info.prev_time.tv_usec = 0;
- xv_dblclick_proc (panel, click_info.idx);
- } else {
- click_info.prev_time = event_time (event);
- }
- xv_panel_grab = 0;
- return;
- }
- if (event_action (event) == ACTION_ADJUST) {
- xv_panel_grab = 0;
- return;
- }
- if (!event_is_button (event) && !event_is_iso (event))
- return;
- xv_panel_grab = 0;
- return;
- } else {
- if (event_action (event) == LOC_DRAG) {
- draw_rubberband (canvas);
- lastx = event_x (event);
- lasty = event_y (event);
- draw_rubberband (canvas);
- return;
- }
- if (event_is_button (event)) {
- if (event_is_down (event)) {
- draw_rubberband (canvas);
- XFreeGC (dpy, xor_gc);
- xv_panel_grab = 0;
- return;
- }
- } else {
- if (event_is_iso (event)) {
- draw_rubberband (canvas);
- XFreeGC (dpy, xor_gc);
- xv_panel_grab = 0;
- }
- return;
- }
- draw_rubberband (canvas);
- xv_panel_grab = 0;
- XFreeGC (dpy, xor_gc);
- xv_rubberband_select (panel);
- return;
- }
- }
- switch (event_action (event)) {
- case ACTION_HELP:
- if (event_is_down (event)) {
- }
- return;
- case ACTION_MENU:
- if (event_is_down (event)) {
- static Menu menu = XV_NULL;
- char *p, *q, c;
-
- if (menu != XV_NULL)
- xv_destroy (menu);
- menu = (Menu) xv_create (XV_NULL, MENU,
- MENU_NOTIFY_PROC, xv_filedepmenu,
- MENU_TITLE_ITEM, panel->dir.list [idx].fname,
- MENU_STRINGS, "Open", "View", "Edit", "Copy", "Move", "Delete", NULL,
- NULL);
- p = regex_command (panel->dir.list [idx].fname, NULL, NULL);
- if (p != NULL) {
- for (;;) {
- while (*p == ' ' || *p == '\t')
- p++;
- if (!*p)
- break;
- q = p;
- while (*q && *q != ' ' && *q != '\t')
- q++;
- c = *q;
- *q = 0;
- xv_set (menu,
- MENU_ITEM,
- MENU_STRING, p,
- NULL,
- NULL);
- if (!c)
- break;
- p = q + 1;
- }
- }
- xv_filedepmenu_panel = panel;
- xv_filedepmenu_idx = idx;
- xv_filedepmenu_free = p;
- menu_show (menu, paint, event, NULL);
- }
- return;
- case ACTION_SELECT:
- case ACTION_ADJUST:
- if (event_is_down (event)) {
- if (in) {
- if (click_info.idx != idx) {
- click_info.idx = idx;
- click_info.prev_time.tv_sec = 0;
- click_info.prev_time.tv_usec = 0;
- }
- click_info.btn_down_x = event_x (event);
- click_info.btn_down_y = event_y (event);
- if (event_action (event) == ACTION_SELECT) {
- if (panel->selected != idx) {
- unselect_item (panel);
- panel->selected = idx;
- select_item (panel);
- }
- } else {
- do_file_mark (panel, idx,
- panel->dir.list [idx].f.marked ? 0 : 1);
- }
- wait_for_btnup = 1;
- xv_panel_grab = 1;
- } else {
- if (event_action (event) == ACTION_SELECT) {
- rubber_adjust = 0;
- lastx = -1;
- startx = -1;
- xv_rubberband_select (panel);
- } else
- rubber_adjust = 1;
- xor_gc = XCreateGC (dpy, xv_get (paint, XV_XID), 0, 0);
- XSetForeground (dpy, xor_gc, xv_get (canvas, WIN_FOREGROUND_COLOR));
- XSetFunction (dpy, xor_gc, GXxor);
- XSetLineAttributes (dpy, xor_gc, 1, LineSolid, CapNotLast, JoinRound);
- lastx = startx = event_x (event);
- lasty = starty = event_y (event);
- wait_for_btnup = 0;
- xv_panel_grab = 1;
- }
- }
- }
- }
-
- static int xv_panel_event_proc (Xv_window paint, Event *event)
- {
- Canvas canvas = (Canvas) xv_get (paint, CANVAS_PAINT_CANVAS_WINDOW);
- WPanel *panel;
-
- panel = (WPanel *) xv_get (canvas, XV_KEY_DATA, KEY_DATA_PANEL);
-
- if (event_is_down (event) && event_is_button (event))
- xv_set_current_panel (panel);
-
- switch (event_action (event)) {
- case ACTION_SELECT:
- case ACTION_ADJUST:
- case LOC_DRAG:
- case ACTION_MENU:
- case ACTION_HELP:
- case ACTION_DRAG_PREVIEW:
- case ACTION_DRAG_COPY:
- case ACTION_DRAG_MOVE:
- case ACTION_DRAG_LOAD:
- xv_mouse_event (canvas, paint, event);
- return 0;
- }
-
- if (event_is_up (event))
- return 0;
-
- switch (event_action (event)) {
- case KBD_USE:
- xv_set_current_panel (panel);
- break;
- case ACTION_GO_COLUMN_FORWARD:
- moveinpanel (canvas, paint, MIP_DOWN);
- break;
- case ACTION_GO_COLUMN_BACKWARD:
- moveinpanel (canvas, paint, MIP_UP);
- break;
- case ACTION_GO_DOCUMENT_START:
- moveinpanel (canvas, paint, MIP_HOME);
- break;
- case ACTION_GO_DOCUMENT_END:
- moveinpanel (canvas, paint, MIP_END);
- break;
- case ACTION_GO_PAGE_BACKWARD:
- moveinpanel (canvas, paint, MIP_PAGEUP);
- break;
- case ACTION_GO_PAGE_FORWARD:
- moveinpanel (canvas, paint, MIP_PAGEDOWN);
- break;
- default:
- if (event_id (event) == '\n' || event_id (event) == '\r') {
- xv_post_proc (midnight_dlg,
- (void (*)(void *))do_enter, (void *) panel);
- } else if (event_id (event) == '\t') {
- if (((Widget *)cmdline)->wdata != (widget_data) NULL)
- xv_set (((Widget *)cmdline)->wdata,
- WIN_SET_FOCUS,
- NULL);
- } else if (event_is_key_left (event) || event_is_key_right (event) ||
- event_is_key_top (event) || event_is_key_bottom (event)) {
- int i = 1;
-
- if (event_is_key_left (event))
- i = event_id (event) - KEY_LEFTFIRST + 1;
- else if (event_is_key_right (event))
- i = event_id (event) - KEY_RIGHTFIRST + 1;
- else if (event_is_key_top (event))
- i = event_id (event) - KEY_TOPFIRST + 1;
- else if (event_is_key_bottom (event))
- i = event_id (event) - KEY_BOTTOMFIRST + 1;
- {
- int j;
- WButtonBar *bb =
- find_buttonbar (midnight_dlg, (Widget *) panel);
-
- if (bb != (WButtonBar *) NULL) {
- if (strcmp (bb->labels [i - 1].text, "PullDn")) {
- if (bb->labels [i - 1].function)
- xv_post_proc (midnight_dlg,
- *bb->labels [i - 1].function,
- bb->labels [i - 1].data);
- }
- }
- }
- }
- }
-
- return 0;
- }
-
- char *xv_create_canvas_gc (Canvas canvas)
- {
- GC gc = XCreateGC (dpy,
- (Drawable) xv_get (xv_get (canvas, CANVAS_NTH_PAINT_WINDOW, 0), XV_XID),
- 0, 0);
-
- XSetFont (dpy, gc, xv_get (xv_get (canvas, XV_FONT), XV_XID));
- XSetLineAttributes (dpy, gc, 1, LineSolid, JoinRound, CapNotLast);
- XSetGraphicsExposures (dpy, gc, False);
-
- return (char *) gc;
- }
-
- void xv_panel_split_proc (Xv_Window origview, Xv_Window newview, int pos)
- {
- Rect *rect = (Rect *) xv_get (
- xv_get (origview, XV_KEY_DATA, KEY_DATA_TILE), DROP_SITE_REGION);
-
- xv_set (newview,
- XV_KEY_DATA, KEY_DATA_TILE, xv_create (newview, DROP_SITE_ITEM,
- DROP_SITE_EVENT_MASK, DND_ENTERLEAVE,
- DROP_SITE_REGION, rect,
- NULL),
- NULL);
-
- free (rect);
- }
-
- int x_create_panel (Dlg_head *h, widget_data parent, WPanel *panel)
- {
- Canvas canvas =
- (Canvas) x_get_parent_object ((Widget *) panel, parent);
- Xv_opaque dropsite_item;
- Xv_window win;
- Rect rect;
-
- rect.r_left = PANELBORDER;
- rect.r_width = 220;
- rect.r_top = PANELBORDER;
- rect.r_height = 220;
- xv_set (canvas,
- XV_KEY_DATA, KEY_DATA_PANEL, panel,
- XV_KEY_DATA, KEY_DATA_PANEL_CONTAINER, xv_get (canvas, XV_OWNER),
- CANVAS_PAINTWINDOW_ATTRS,
- WIN_CONSUME_EVENTS,
- KBD_DONE, KBD_USE, WIN_ASCII_EVENTS, WIN_LEFT_KEYS, WIN_TOP_KEYS,
- WIN_RIGHT_KEYS, WIN_META_EVENTS, WIN_EDIT_KEYS, WIN_MOTION_KEYS,
- WIN_TEXT_KEYS,
- WIN_UP_EVENTS, WIN_MOUSE_BUTTONS, LOC_DRAG,
- ACTION_HELP, ACTION_DRAG_PREVIEW, ACTION_DRAG_LOAD, ACTION_DRAG_COPY,
- ACTION_DRAG_MOVE,
- NULL,
- WIN_EVENT_PROC, xv_panel_event_proc,
- NULL,
- CANVAS_X_PAINT_WINDOW, FALSE,
- CANVAS_RETAINED, FALSE,
- CANVAS_REPAINT_PROC, xv_panel_repaint_proc,
- WIN_CMS, mccms,
- OPENWIN_SPLIT,
- OPENWIN_SPLIT_INIT_PROC, xv_panel_split_proc,
- NULL,
- NULL);
-
- CANVAS_EACH_PAINT_WINDOW (canvas, win)
- xv_set (win,
- XV_KEY_DATA, KEY_DATA_TILE, xv_create (win, DROP_SITE_ITEM,
- DROP_SITE_EVENT_MASK, DND_ENTERLEAVE,
- DROP_SITE_REGION, &rect,
- NULL),
- NULL);
- CANVAS_END_EACH
-
- panel->widget.wdata = (widget_data) canvas;
- panel->gc = xv_create_canvas_gc (canvas);
- panel->font = (void *) xv_get (canvas, XV_FONT);
- panel->ascent = ((XFontStruct *) xv_get (
- xv_get (canvas, XV_FONT), FONT_INFO))->ascent;
- panel->descent = ((XFontStruct *) xv_get (
- xv_get (canvas, XV_FONT), FONT_INFO))->descent;
- panel->item_height = panel->ascent + panel->descent;
- if (panel->item_height < 16)
- panel->item_height = 16;
- panel->item_height += 2 * PANELITEMBORDER;
- x_fill_panel (panel);
- return 1;
- }
-
- void x_panel_set_size (int idx)
- {
- }
-
- void set_attr (int h, int m)
- {
- }
-